package com.eatme.core.sort;

import com.eatme.core.array.ArrayGenerator;

import java.util.Arrays;
import java.util.Random;

/**
 * 双路快速排序
 */
public class QuickSortV4 {
    private QuickSortV4() {

    }

    public static <E extends  Comparable<E>> void sort(E[] arr) {
        Random rnd = new Random();
        sort(arr,0,arr.length-1,rnd);
    }

    private static <E extends  Comparable<E>> void sort(E[] arr, int l, int r, Random rnd) {
        if (l>=r) return;
        int p = partition(arr,l,r,rnd);
        sort(arr,l,p-1, rnd);
        sort(arr,p+1,r, rnd);
    }

    private static <E extends  Comparable<E>> int partition(E[] arr,int l,int r,Random rnd) {

        // 生成[l,r] 之间的随机索引
        int p = l+rnd.nextInt(r-l+1);
        swap(arr,l,p);
        // arr[l+1...j] <= v; arr[j+1...i] >= v
        int i = l+1,j=r;
        while (true) {
            while (i<=j && arr[i].compareTo(arr[l])<0)
                i++;
            while (j>=i&&arr[j].compareTo(arr[l])>0)
                j--;
            if (i>=j) break;
            swap(arr,i,j);
            i++;
            j--;
        }
        swap(arr,l,j);
        return j;
    }

    private static <E> void swap(E[] arr, int i, int j) {
        E t = arr[i];
        arr[i] =arr[j];
        arr[j] =t;
    }

    public static void main(String[] args) {
        int n = 1000000;
        System.out.println("RandomArray");
        Integer[] arr =ArrayGenerator.generateRandomArray(n,n);
        Integer[] arr4_3 = Arrays.copyOf(arr,arr.length);
        Integer[] arr4_4 = Arrays.copyOf(arr,arr.length);
        SortingHelper.sortTest("QuickSortV3",arr4_3);
        SortingHelper.sortTest("QuickSortV4",arr4_4);

        System.out.println("OrderedArray");
        Integer[] arr5 =ArrayGenerator.generateOrderedArray(n);
        Integer[] arr6 = Arrays.copyOf(arr5,arr.length);
        SortingHelper.sortTest("QuickSortV4",arr6);
        SortingHelper.sortTest("QuickSortV3",arr5);


        System.out.println("SameValueArray");
        Integer[] arr1_3 =ArrayGenerator.generateRandomArray(n,1);
        Integer[] arr1_3_2 = Arrays.copyOf(arr1_3,arr.length);
        SortingHelper.sortTest("QuickSortV4",arr1_3);
        // SortingHelper.sortTest("QuickSortV3",arr1_3_2); // StackOverflowError
    }
}
